/*********************************************************
                fpc/file/ace_merge.c 
*********************************************************/
#include "fpp.h"
#include <fcntl.h>
#include <float.h>
#include <malloc.h>
#include <strings.h>

extern int Zbatch_flag;
extern BOOL  dataloaded;
extern BOOL merging;
extern void getdatehead(), save_fpc_safe();
extern int graphQueryOpen();
extern void sortoutmarkersman();
extern void markersinctgcount();
extern void clearallmaps();
extern int getcomment();
extern void recalccontigs();
extern int save_fpc();

int merge(), dequote();
BOOL fppFind(Array a, char *s, int *ip, BOOL (* order)());
BOOL fppInsert(Array a, char *s, int *index, BOOL (*order)());
BOOL cloneOrder(void *s, void *b);
BOOL markerOrder(void *s, void *b);
void displaymess(char *text);
void settime(struct mytime *mytime);
void SetCtgForMatchingClones(void);
void removeCloneFromMarkersList(int editclone,int markerindex);
int clonefreemarkermem();
int readmarkerfile(FILE *fpace, int type);
void suffixremove(char*);

char clone_marks[CLONE_MARKER_MAX][MARKER_SZ+1];
static int del_clone_marks;
static int merge_flag=0;
static void read_framework(), readSeq(), printmarkers();
static int ace_debug=0;

/*************************************************/
int get_ace_clone(char *junk)
{
int i, rc = -1;
   for (i=0; i<clonetypenum && rc == -1; i++)
      if (strncasecmp(clonetype[i],junk,strlen(clonetype[i]))==0) rc=i;
return rc;
}
/*************************************************/
int get_ace_marker(char *junk)
{
int rc = -1;
int get_fpc_marker();

  if(strstr(junk,"ePCR_Positive_")) return markPCR;
  if (strncmp("Positive_", junk, 9) == 0) {
    if ((rc = get_fpc_marker(junk))!= -1) return rc;
       /* cari 14.5.4 these should be obsolete */
    if(strstr(junk,"Positive_probe")) return markPROBE;
    else if(strstr(junk,"Positive_locus")) return markLOCUS;
    else if(strstr(junk,"Positive_cosmid")) return markCOSMID;
    else if(strstr(junk,"Positive_fosmid")) return markFOSMID;
    else if(strstr(junk,"Positive_cDNA")) return markCDNA;
    else if(strstr(junk,"Positive_ePCR")) return markPCR; /* CAS 8/31/01 */
  }
  else if (strstr(junk,"Reported_positive_probe")) return markPROBE;
  else if (strstr(junk,"Reported_positive_STS")) return markSTS;
  return -1;
}
/******************************************************************
                       DEF: replaceFW
file.... item, Replace framework
******************************************************************/
void replaceFW() 
{
  FILE *fpace;
  char fileName[MAXPATHLEN+1];

  if(dataloaded){
    fpace = (FILE *)graphQueryOpen(mergedir, mergefile, "fw","r","Choose framework file");
    sprintf(fileName, "%s/%s", mergedir, mergefile);
    if(fpace!=0) { 
      update=TRUE;  
      read_framework(fpace, fileName);
    }
    else return;
  }
  else{
    displaymess("No project has been loaded yet.");
    displaymess("Therefore cannot merge");
    return;
  }
}
/******************************************************************
                       DEF: open_framework
file... item, Replace markers (fw & seq)
******************************************************************/
static void open_framework()
{
  FILE *fp;
  char junk[255];
  char fileName[MAXPATHLEN+1];
  
  if (merge_flag) return;
 
  sprintf(fileName, "%s/framework", mergedir);
  if((fp = fopen(fileName,"r")) == NULL ){
    sprintf(fileName, "framework");
    if((fp = fopen(fileName,"r")) == NULL ){
      sprintf(fileName,"%s/%s.fw", mergedir, mergefile);
      if((fp = fopen(fileName,"r")) == NULL ){
        sprintf(fileName,"%s.fw",  mergefile);
        if((fp = fopen(fileName,"r")) == NULL ){
          sprintf(fileName,"%s/%s.global",  mergedir, mergefile);
          if((fp = fopen(fileName,"r")) == NULL ){
            sprintf(fileName,"%s.global",  mergefile);
            if((fp = fopen(fileName,"r")) == NULL ){
	       sprintf(junk,"No framework map %s %s", mergedir, mergefile);
	       displaymess(junk);
	       return; /* thats ok - no file, no globals */
	    }
          }
        }
      }
    }
  }
  read_framework(fp, fileName);
}
/******************************************************************
                       DEF: read_old_framework
fred 6/02/03 -- old format for backwards compatibility
******************************************************************/
static void read_old_framework(FILE *fp, int use_chrom, int rewrite, char *fw_file)
{
  int i;
  char *ptr1, *ptr2, junk[255], name[MARKER_SZ+1], map[50];
  char anchor_bin[ANCHOR_BIN_SZ+1];
  int err=0, index, new=0, cnt=0, cnt1=0, cnt2=0;
  float pos, anchor_pos;
  int frame_type;
  char tmp[20];
  int first=TRUE;
  FILE *fp2=NULL;
  char cmd_str[MAXPATHLEN*2+10];
  MARKER *mkp;

  for (i=0; i< arrayMax(markerdata); i++) {
       arrp(markerdata,i,MARKER)->anchor_pos = FLT_MIN;
       arrp(markerdata,i,MARKER)->anchor_bin[0] = '\0';
       arrp(markerdata,i,MARKER)->anchor = FALSE;
  }
  if (strstr(Proj.mapname,"ctg")!=NULL) Proj.mapname[0] = '\0'; /* temp fix */
 
  if(use_chrom){
    strcpy(Proj.anchor_label,"Chromosome");
    strcpy(Proj.label_abbrev,"Chr");
  }
  else{
    strcpy(Proj.anchor_label,"");
    strcpy(Proj.label_abbrev,"");
  }

  if(rewrite){
    /*Rewrite with new format*/
    printf("Moving old framework to %s.old\n",fw_file);
    sprintf(cmd_str,"mv %s %s.old",fw_file, fw_file);
    system(cmd_str);
    if((fp2=fopen(fw_file, "w"))==NULL){
      printf("ERROR: file %s not rewritten: ",fw_file); perror(NULL);
      rewrite=FALSE;
    }
  }

  while(fgets(junk,255,fp) != NULL){
    for (i=0; i<255 && (junk[i] == ' ' || junk[i] == '\t'); i++);
    if(junk[i]=='\n' || i==255) continue;

    if (!dequote(junk, name, MARKER_SZ)) continue;

    ptr1 = strstr(junk, ";")+1;
    if (!dequote(ptr1, map, MARKER_SZ)) continue;

    if (strstr(map,"ctg")!=NULL) printf("Erroneous map name %s\n",map);
    else if (Proj.mapname[0]=='\0') strcpy(Proj.mapname, map);
    else if (strcmp(Proj.mapname,map)!=0 && !err)  {
	printf("Different map names %s and %s\n",map, Proj.mapname);
	err=1;
    }

    ptr2 = strstr(ptr1, ";")+1;
    if (sscanf(ptr2, "%f;", &pos)!=1) continue;

    if(use_chrom){   /* fred 6/2/03*/
      sprintf(tmp, "%.1f", pos);
      sscanf((char *)&tmp[strlen(tmp)-5], "%f", &anchor_pos);
      tmp[strlen(tmp)-5] = '\0';
      strcpy(anchor_bin, tmp);
    }
    else{
      anchor_pos = pos;
    }
    if (strstr(ptr2, "Frame")) frame_type = FRAME;
    else frame_type = PLACE;

    if(first && rewrite){
      fprintf(fp2, "Map \"%s\"\n",Proj.mapname);
      fprintf(fp2, "Label \"%s\"\n",Proj.anchor_label);
      fprintf(fp2, "Abbrev \"%s\"\n",Proj.label_abbrev);
      first=FALSE;
    }
    if(fppFind(markerdata,name,&index, markerOrder)){
      mkp=arrp(markerdata,index,MARKER);
      if(mkp->anchor == FALSE) {
        printf("New framework marker %s\n",name);
        new++; 
      }
      mkp->anchor = TRUE;
      if (frame_type==FRAME) cnt++;
      else cnt1++;
      mkp->frame_type = frame_type;
      mkp->anchor_pos = anchor_pos;
      if(use_chrom)
        strcpy(mkp->anchor_bin, anchor_bin);
    } 
    else cnt2++;

    if(rewrite){
      fprintf(fp2, "%-15s %-8s %-7.1f %c\n", name, anchor_bin, 
              anchor_pos, frame_type==FRAME ? 'F' : 'P');
    }
  }
  fclose(fp);
  if(rewrite) fclose(fp2);
  sprintf(junk,"Framework %d  Placement %d  New %d  Ignored %d",cnt, cnt1, new, cnt2);
  displaymess(junk);
  if (new>0) update = TRUE;
}

/******************************************************************
                       DEF: check_framework_format
There are currently 6 types of framework styles supported:
1) %d
2) %d.%d
3) %dq%d
4) %dq%d.%d
5) %c
6) %c.%d
If str is not in one of these formats, return 0.
******************************************************************/
static int
check_framework_format(char *str){
  int i1, i2, i3;
  char c1;
  char s1[50];

  if(sscanf(str,"%d%s",&i1, s1)==1) return 1;
  if(!strcmp(str,"X") || !strcmp(str,"x") ||
     !strcmp(str,"Y") || !strcmp(str,"y")) return 1;
  if(sscanf(str,"%d.%d%s",&i1, &i2, s1)==2) return 2;
  if(sscanf(str,"%*[XxYy].%d%s",&i1, s1)==1) return 2;
  if(sscanf(str,"%d%*[PpQq]%d%s",&i1, &i2, s1)==2) return 3;
  if(sscanf(str,"%*[XxYy]%*[PpQq]%d%s",&i1, s1)==1) return 3;
  if(sscanf(str,"%d%*[PpQq]%d.%d%s",&i1, &i2, &i3, s1)==3) return 4;
  if(sscanf(str,"%*[XxYy]%*[PpQq]%d.%d%s",&i1, &i2, s1)==2) return 4;
  if(sscanf(str,"%c%s",&c1,s1)==1) return 5;
  if(sscanf(str,"%c.%d%s",&c1,&i1,s1)==2) return 6;
  return 0;
}

/******************************************************************
                       DEF: read_new_framework
cari 18.8.6 - Replace frameworks was not clearing old frameworks
I think I added that so as to show the New frameworks. But its done right
now, where it tracks what is to be removed.
******************************************************************/
static void read_new_framework(FILE *fp)
{
  int cnt_remove=0, i, index, new=0, cnt2=0, cntP=0, cntF=0;
  char junk[256];
  char map[50];
  char arg1[50], arg2[50], arg3[50], arg4[50];
  char name[MARKER_SZ+1], anchor_bin[ANCHOR_BIN_SZ+1];
  float anchor_pos;
  int frame_type;
  int arg_num;
  MARKER *mkp;
  int use_anchor_bin;
  int *remove;

  remove =  malloc(sizeof(int) * arrayMax(markerdata)+1);
  for (i=0; i< arrayMax(markerdata); i++) {
       remove[i] = arrp(markerdata,i,MARKER)->anchor; 
  }
  
  Proj.mapname[0]='\0';
  Proj.anchor_label[0]='\0';
  Proj.label_abbrev[0]='\0';
  Proj.generic_grpnames = 0;

  while(fgets(junk,255,fp) != NULL){
    if (junk[0] == '#') continue;
    if (!strncmp(junk, "//", 2)) continue;
    if(strstr(junk,"Map")!=NULL){
      /* WMN support for arbitrary chr names */
      if (strstr(junk,"generic_grpnames"))
      {
         Proj.generic_grpnames = 1;
      }
      if (!dequote(junk, map, 49)) continue;
      if (strstr(map,"ctg")!=NULL) printf("Erroneous map name %s\n",map);
      else strcpy(Proj.mapname, map);
    }
    else if(strstr(junk,"Label")!=NULL){
      if (!dequote(junk, Proj.anchor_label, 49)) continue;

    }
    else if(strstr(junk,"Abbrev")!=NULL){
      if (!dequote(junk, Proj.label_abbrev, 49)) continue;
    }
    else{
      arg_num=sscanf(junk, "%s %s %s %s", arg1, arg2, arg3, arg4);
      if(arg_num==3){   /*No anchor bins*/
        use_anchor_bin=FALSE;
        strcpy(name, arg1);
        strcpy(anchor_bin, "");
        sscanf(arg2, "%f", &anchor_pos);
        if(!strncmp(arg3, "F", 1)) frame_type = FRAME;
        else frame_type = PLACE;

      }
      else if(arg_num==4){
        use_anchor_bin=TRUE;
        strcpy(name, arg1);
        strcpy(anchor_bin, arg2);
        sscanf(arg3, "%f", &anchor_pos);
        if(!strncmp(arg4, "F", 1)) frame_type = FRAME;
        else frame_type = PLACE;
      }
      else{
        printf("Bad input line ignored: %s\n",junk);
        continue;
      }

/* WMN
      if(first && use_anchor_bin){
	format=check_framework_format(anchor_bin);
	if(format==0){
	  printf("ERROR: Unsupported framework format: %s\n",anchor_bin);
	  return;
	}
	strcpy(pattern, anchor_bin);
	first=FALSE;
      }
      else if(use_anchor_bin){
	if(format!=check_framework_format(anchor_bin)){
	  printf("ERROR: inconsistent framework formats: %s and %s\n",pattern, anchor_bin);
	  return;
	}
      }
*/

      if(fppFind(markerdata,name,&index, markerOrder)){
        mkp = arrp(markerdata,index,MARKER);
        if (mkp->anchor == FALSE) new++; 
        if (frame_type==FRAME)  cntF++;
        else cntP++;
        
        strcpy(mkp->anchor_bin, anchor_bin);
        mkp->anchor_pos = anchor_pos;
        mkp->frame_type=frame_type;
        mkp->anchor=TRUE;
        remove[index] = FALSE;
      }
      else cnt2++;
    }
  }
  if((Proj.label_abbrev[0]=='\0') && (Proj.anchor_label[0]!='\0')){
    /* No abbreviation was defined*/
    strcpy(Proj.label_abbrev, Proj.anchor_label);
    if(strlen(Proj.label_abbrev) > 3)
      Proj.label_abbrev[3]='\0';
  }
  for (i=0; i< arrayMax(markerdata); i++) {
     if (remove[i] == TRUE) {
       arrp(markerdata,i,MARKER)->anchor_pos = FLT_MIN;
       arrp(markerdata,i,MARKER)->anchor_bin[0] = '\0';
       arrp(markerdata,i,MARKER)->anchor = FALSE;
       cnt_remove++;
     }
  }
  free(remove);
    
  sprintf(junk,"Framework %d  Placement %d  New %d  Removed %d  Ignored %d",
                 cntF, cntP, new, cnt_remove, cnt2);
  displaymess(junk);
  if (new>0) update = TRUE;
}

/******************************************************************
                       DEF: read_framework
******************************************************************/
static void read_framework(FILE *fp, char *fw_file){
  char junk[256];
  int rewrite=FALSE;
  int use_chrom=FALSE;
  char *rc;

  while ((rc = fgets(junk,255,fp)) != NULL && 
         (junk[0]=='#' || !strncmp(junk,"//",2)));
  if (rc==NULL) {
      printf("No data in file - all frameworks will be removed\n");
      read_new_framework(fp);
      return;
  }
  rewind(fp);
  if(!strncmp(junk, "Map", 3)) {   /*New format*/
      read_new_framework(fp);
      return;
  }
  if(messQuery("Selected framework file appears to be in an old format.  \
Rewrite to a new file with new format (Recommended)?"))
        rewrite=TRUE;
  if(messQuery("Is the chromosome number imbedded in the global position?"))
        use_chrom=TRUE;
  read_old_framework(fp, use_chrom, rewrite, fw_file);
}

/****************************************************************
                       DEF: replaceSeq
*****************************************************************/
void replaceSeq()
{
  FILE *fpace;

  if(dataloaded){
    fpace = (FILE *)graphQueryOpen(mergedir, mergefile, "ace","r","Choose sequence status file");
    if (fpace==0) return;
#ifdef SANGER
  readSeq_old(fpace);
#else
  readSeq(fpace);
#endif
  }
  else{
    displaymess("No project has been loaded yet.");
    displaymess("Therefore cannot merge");
    return;
  }
}
/******************************************************************
                       DEF: sequencenew
This is read in the Replace markers (fw&seq) where file has fixed name
******************************************************************/
static void sequencenew()
{
  FILE *fp;
  char junk[255];

  if((fp = fopen(messprintf("%s/sequencesnew.ace", mergedir),"r")) == NULL )
    if((fp = fopen("sequencesnew.ace","r")) == NULL )
       return; /* thats ok - no file, no sequence */

  if(fgets(junk,255,fp) == NULL) {
    printf("ERROR reading sequencenew.ace file\n");
    return;
  }
#ifdef SANGER
  readSeq_old(fp);
#else
  readSeq(fp);
#endif
}
/*******************************************************************
                   readSeq
called by File... Replace Sequence
*****************************************************************/
static void readSeq(FILE *fp)
{
  int i;
  char junk[255], name[MARKER_SZ+1], tmp[255];
  int index = -1, cnt=0;
  CLONE *clp=NULL; 
  struct remark *last, *prev;
  int dupFlag;

  if(messQuery("Clear all current Sequence status?")) {
      for (i=0; i< arrayMax(acedata); i++) 
          arrp(acedata, i, CLONE)->seqstat = 0;
  }
  while(fgets(junk,255,fp) != NULL)
  {
    if (junk[0]=='/') continue;
    for (i=0; i<255 && (junk[i] == ' ' || junk[i] == '\t'); i++);
    if(junk[i]=='\n' || i==255) continue;

    if (get_ace_clone(junk) != -1)
    {
       if (dequote(junk, name, CLONE_SZ -1)==0){
	 printf("ERROR sequence file has string *%s*",junk);
         index = -1;
         continue;
       }
       if(fppFind(acedata,name,&index,cloneOrder)){
	  clp = arrp(acedata, index, CLONE);    
          cnt++;
       }
       else index = -1;
       continue;
    }
    if (index == -1) continue; /* in the middle of an non-fpc clone */

    if (strncmp("Shotgun",junk, 7)==0) {
       if (strstr(junk, "SHOTGUN")!=NULL) clp->seqstat = SHOTGUN;
       else if (strstr(junk, "TILE")!=NULL) clp->seqstat = TILE;
       else if (strstr(junk, "READY")!=NULL) clp->seqstat = READY;
       else if (strstr(junk, "CANCELLED")!=NULL) clp->seqstat = CANCELLED;
       else if (strstr(junk, "SENT")!=NULL) clp->seqstat = SENT;
       else if (strstr(junk, "FINISHED")!=NULL) clp->seqstat = FINISHED;
       else if (strstr(junk, "Full_X")!=NULL) clp->seqtype = FULLX;
       else if (strstr(junk, "Half_X")!=NULL) clp->seqtype = HALFX;
    }
    if (strncmp("Remark",junk, 6)==0) {
        getcomment(junk, tmp, COMMENT_SZ-1);
        if(clp->remark==NULL){
           clp->remark = (struct remark *)messalloc((sizeof(struct remark)));
           last = clp->remark;
           strcpy(last->message, tmp);
           last->next = NULL;
           settime(&clp->modified_date);
        }
        else{
          dupFlag = 0;
          for(last=clp->remark;(last!=NULL) && (!dupFlag);last=last->next){
              if (strcmp(last->message,tmp)==0) dupFlag = 1;
              prev=last;
          }
          if (!dupFlag) {
             prev->next  = (struct remark *)messalloc((sizeof(struct remark)));
             last = prev->next;
             strcpy(last->message, tmp);
             last->next = NULL;
             settime(&clp->modified_date);
          }
        }
    }
  }
  fclose(fp);
  printf("Read %d sequence records\n",cnt);
  recalccontigs();
  if (cnt>0) update = TRUE;
}

/**************************************************************
                     DEF: mergeSAM
Called from File... Merge markers (it used to require the keyword SAM in header)
**************************************************************/
void mergeSam() 
{
  FILE *fpace;

  if(dataloaded){
    fpace = (FILE *)graphQueryOpen(mergedir, mergefile, "ace","r","Choose framework file");
    if(fpace!=0)  {
       readmarkerfile(fpace, 0);
       sortoutmarkersman();   /* position the markers */
       markersinctgcount(); /* redo contig counts */
       update = TRUE;  
       clearallmaps();
    }
    else return;
  }
  else{
    displaymess("No project has been loaded yet.");
    displaymess("Therefore cannot merge");
    return;
  }
}
void replaceMrksBatch(char* mrkfile)
{
    FILE* fpace;
    fpace = (FILE *)fopen(mrkfile,"r");
    if(fpace!=0)  
    {
       readmarkerfile(fpace, 0);
       sortoutmarkersman();   /* position the markers */
       markersinctgcount(); /* redo contig counts */
       update = TRUE;  
       clearallmaps(); 
       okaytowrite = 1;
       save_fpc(); 
    }
    else
    {
        fprintf(stderr,"Unable to open marker file %s\n",mrkfile);
    } 
}
/****************************************************************
                     DEF: read_sam
SAM is a program for ordering markers, and the output can be used
as a framework in FPC. This gets called at the beginning of readmarkerfile
and does all the work except read the header and print stats
****************************************************************/
static void read_sam(FILE *fpace)
{
char junk[255], name[MARKER_SZ];
int i;
int index;
struct marker *marker=NULL;
int cnt=0, cnt1=0, cnt3=0;

  if (Proj.mapname[0]=='\0') strcpy(Proj.mapname, fileName);
  printf("Reading SAM file\n");
  while(fgets(junk,255,fpace) != NULL){
    for (i=0; i<255 && (junk[i] == ' ' || junk[i] == '\t'); i++);
    if(junk[i]=='\n' || i==255) continue;
    
    if(strncmp(junk,"Marker_",7)==0)
    {
      if (dequote(junk, name, MARKER_SZ)==0){                
	fprintf(stderr,"ERROR string *%s no DATA\n",junk);
	exit(0);
      }
      if(fppFind(markerdata,name,&index,markerOrder))
	marker = arrp(markerdata,index,MARKER);
      else 
        marker = NULL;
      continue;
    }
    if (marker==NULL) continue;

    if(strncmp(junk,"Global_",7)==0) {
      if (marker->frame_type == 0) cnt++; else cnt1++;
      sscanf(junk,"Global_position %f",&(marker->anchor_pos));
      marker->anchor_bin[0]='\0';
      marker->anchor = TRUE;
      marker->frame_type = FRAME;
    }
    else if (strncmp(junk,"No_Global",9)==0) {
      cnt3++;
      marker->anchor = FALSE;
      marker->frame_type = 0;
      marker->anchor_pos = 0;
    }
  }
  if (cnt3 > 0) 
    sprintf(junk,"Framework Markers  Add %d  Update %d  Remove %d",cnt, cnt1, cnt3);
  else
    sprintf(junk,"Framework Markers  Add %d  Update %d",cnt, cnt1);
  displaymess(junk);
  
}
/*******************************************************************
                  DEF: replaceMarkers
********************************************************************/
int replaceMarkers(void)
{
  FILE *fpace;

  if(dataloaded){
    fpace = (FILE *)graphQueryOpen(mergedir, mergefile, "ace","r","Choose merge file");
    suffixremove(mergefile);
    if(fpace!=0)  {
       if (readmarkerfile(fpace, 1)) {
          open_framework();
          sequencenew();
          sortoutmarkersman();   /* position the markers */
          markersinctgcount(); /* redo contig counts */
          if (ace_debug) printmarkers("DONE");
          update = TRUE;  
          clearallmaps();
          return 1;
       }
       else return FALSE;
    }
    else
      return(-1);
  }
  else{
    displaymess("No project has been loaded yet.");
    displaymess("Therefore cannot merge");
    return(-1);
  }
}
/****************************************************************
                     DEF: removemarks
****************************************************************/
int removemarks(int m, int index)
{
int i, f;
int  found=0, index2;
struct marker *mptr;
CLONE *clp;
struct markertop *ptr;
struct markerctgpos *pos;
struct markerclone *mc;

  if (m==0) return 0;
  if (merge_flag) return 0;

  clp = arrp(acedata,index,CLONE);
  if(clp->marker == NULL) return 0; 

  for (f=i=0; i< m; i++) 
  {
     if (clone_marks[i][0] == '\0') continue;
     if(!fppFind(markerdata,clone_marks[i],&index2, markerOrder)) continue;

     del_clone_marks++;

     if(strcmp(clp->marker->marker,clone_marks[i])==0) 
          clp->marker = clp->marker->nextmarker;
     else{
        for (ptr=clp->marker; ptr->nextmarker != NULL; ptr=ptr->nextmarker)
	    if(strcmp(ptr->nextmarker->marker,clone_marks[i])==0) {
	        ptr->nextmarker = ptr->nextmarker->nextmarker;
                break;
	    }
     }
     if (arr(markerdata, index2, MARKER).nextclone!=NULL) {
         mptr = arrp(markerdata,index2,MARKER);
         settime(&mptr->modified_date);
         if (ace_debug) printf("Removelist %s from %s\n",mptr->marker,clp->clone);
         removeCloneFromMarkersList(index, index2); 

         if (arrp(acedata, mptr->cloneindex, CLONE)->ctg == clp->ctg) found=1;
         else 
           for (mc=mptr->nextclone; mc!=NULL && 
                         mc->nextclone!=NULL && !found; mc=mc->nextclone) 
                if (arrp(acedata, mc->cloneindex, CLONE)->ctg == clp->ctg) found=1;

         if (!found) {
	     if(mptr->pos != NULL){
	       if(mptr->pos->ctg ==  clp->ctg) 
		 mptr->pos = mptr->pos->next;
	       else{
		 for (pos=mptr->pos; pos->next != NULL; pos=pos->next)
		   if(pos->next->ctg == clp->ctg) {
		     pos->next = pos->next->next;
		     break;
		   }
	       }
	     }
         }
     }
     else {
         arrp(markerdata, index2, MARKER)->cloneindex = -1;
         if (ace_debug) printf("Remove marker %s from clone %s\n",
                  arrp(markerdata, index2, MARKER)->marker, clp->clone);
     }
     f++;
  }
return f;
}

/******************************************************************
                       DEF: addremark
******************************************************************/
void addremark(char *junk,int index)
{
  CLONE *clone;
  struct remark *last, *ptr;
  
  if(index ==-1) return;

  clone = arrp(acedata,index,CLONE);
  last = clone->remark;
      /* do not put in duplicate remark */
  while(last !=NULL){ // CAS Apr06 removed a Sanger specific looking for Picked_by 
      if(strcmp(junk,last->message)==0) return;
      ptr=last;
      last = last->next;
  }
  if(clone->remark==NULL){
      clone->remark = (struct remark *)messalloc((sizeof(struct remark)));
      ptr = clone->remark;
  }
  else{
      ptr->next  = (struct remark *)messalloc((sizeof(struct remark)));
      ptr = ptr->next;
  }
  strcpy(ptr->message,junk);
  ptr->next = NULL;
}

/******************************************************************
                       DEF: addfpremark
efriedr -- removed static specifier -- function needed in clam/bss.c
******************************************************************/
void addfpremark(char *junk,int index)
{
  CLONE *clone;
  struct remark *last, *ptr;
  
  if(index !=-1){
    clone = arrp(acedata,index,CLONE);
    last = clone->fp_remark;
    while(last !=NULL){
      if(strcmp(junk,last->message)==0)
	return;
      if (strncmp(junk,"Pick_by", 7)==0 && strncmp(last->message,"Pick_by", 7)==0) {
         if (strlen(junk) < COMMENT_SZ) strcpy(last->message, junk);
         else printf("Pick_by remark greater than remark size for clone %s\n",
             clone->clone);
         return;
      }
      ptr=last;
      last = last->next;
    }
    if(clone->fp_remark==NULL){
      clone->fp_remark = (struct remark *)messalloc((sizeof(struct remark)));
      ptr = clone->fp_remark;
    }
    else{
      ptr->next  = (struct remark *)messalloc((sizeof(struct remark)));
      ptr = ptr->next;
    }
    strcpy(ptr->message,junk);
    ptr->next = NULL;
  }
}

#define GRIDTXTSIZE 15  
/******************************************************************
                       DEF: readmarkerfile - read merge file
******************************************************************/
int readmarkerfile(fpace, type)
FILE *fpace;
int type;
{
  BOOL addit;
  char junk[255], name[200],grid[GRIDTXTSIZE];
  int i, cm=-1;
  int index = -1, index2 = -1;
  CLONE *clone=NULL, *clp; 
  struct markerclone *markclptr;
  struct marker marker, *mkptr;
  struct markertop *mptr, *toppointer;
  int markertype= 0,linenum = 0;
  int clonemarks=0, newmarkers = 0,updateclones=0, updatemarkers = 0;
  char str1[80], pick[80];
  int  c_rm=0, chg=0, removed=0,j;
  Array markerdata2;
  int t=0, weak,markernum;
  int confirmed=0, electronic=0, c,  marktypechg=0;

  merge_flag = !type;
  del_clone_marks=0;
  markernum = arrayMax(markerdata);
  for(i=0;i<arrayMax(markerdata);i++){
    mkptr = arrp(markerdata,i,MARKER);
    mkptr->status = -1;
  } 
  for(i=0;i<arrayMax(acedata);i++)
    arrp(acedata,i,CLONE)->selected = 1;

  if (ace_debug) printmarkers("start");
  if (type==0) printf("Before Merge Markers %d\n",markernum);
  else printf("Before Replace Markers %d\n",markernum);

 /** cari 14.5.4 - remove need for SAM on first line for Merge Marker **/ 

  while(fgets(junk,255,fpace) != NULL)
  {
    linenum++;
    if (junk[0]=='/') {
       if (linenum==1 && (strstr(junk,"SAM")!=0 || strstr(junk,"Framework")!=0)) {
          merge_flag=1;
       }
       continue;
    }
    if (linenum % 100 == 0) {
        if (graphInterruptCalled())
        {
          printf("User Interrupt - pre-mature termination of Merge markers\n");
          return 0;
        }
    }
    
    for (i=0; i<255 && (junk[i] == ' ' || junk[i] == '\t'); i++);
    if(junk[i]=='\n' || i==255) continue;
    
    if (merge_flag && strncmp(junk,"Markerdata",10)==0) {
       read_sam(fpace); /* reads a SAM output file */
       break;
    }
    if(get_ace_clone(junk) != -1){
       if (index != -1) { /* finish current clone */
          if (removemarks(cm,  index)) {c_rm++; chg = 1;}
          if (pick[0]!='\0') addfpremark(pick, index);
          if (chg) {
              settime(&(clone->modified_date)); 
              updateclones++;
          }
       }
       pick[0]='\0';
       cm=chg=0;
       if (dequote(junk, name, CLONE_SZ)==0){
	 fprintf(stderr,"ERROR line %d is %s",linenum, junk);
         index = -1;
         continue;
       }
       if(fppFind(acedata,name,&index,cloneOrder)){
	  clone = arrp(acedata, index, CLONE);    
          if (clone->selected == 0) {
             printf("Duplicate %s - ignoring it\n",clone->clone);
             continue;
          }
          clone->selected = 0;
          t++;
          for (cm=0, mptr= clone->marker; mptr!=NULL; cm++, mptr = mptr->nextmarker)
          {
                 strcpy(clone_marks[cm],mptr->marker);
                 if (cm >= CLONE_MARKER_MAX) {
                    printf("Exceeded marker limit %d for clone %s\n",CLONE_MARKER_MAX,
                           clone->clone);
                    continue;
                 }
          }
       }
       else index = -1;
       continue;
    }
    if (index == -1) continue; /* in the middle of an non-fpc clone */

    if (strncmp("In_situ",junk,7)==0) {
        if(dequote(junk,str1,80)){
          sprintf(pick, "FISH %s",str1);
          addfpremark(pick,index);
      }
      continue;
    }
    if(strncmp("Gridded",junk,7)==0){
      if(dequote(junk,grid,GRIDTXTSIZE)){
	if(strncmp("SC22",grid,4)==0)
	  addfpremark(grid,index);
      }
      continue;
    }
    if(strncmp("Picked_off_by",junk,12)==0){ /* add 7apr99 */
      if(dequote(junk,grid,GRIDTXTSIZE)){
        if (pick[0]=='\0') sprintf(pick, "Pick_by %s", grid);
        else {
           strcat(pick, " ");
           strcat(pick, grid);
        }
      }
      continue;
    }
    if (strncmp(junk, "End_sequence", 12) == 0) {
       addfpremark("End_sequence", index);
       continue;
    } 
    if ((markertype = get_ace_marker(junk)) == -1) continue; 

    if(dequote(junk, name , MARKER_SZ)==0){ 
       fprintf(stderr,"ERROR line %d is %s",linenum, junk);
       continue;
    }
#ifdef SANGER
/* just added the ifdef on 12dec00
          change st to e on ePCR markers so will not conflict with STS with same name*/
    if (markertype==markPCR) {
        char tmp[CLONE_SZ];
        strcpy(tmp,&(name[1]));
        sprintf(name,"e%s",tmp);
    }
#endif
    weak =  (strstr(junk, "_weak")!=NULL) ? 1 : 0;
               /* got a marker for an fpc-clone */
    addit = TRUE;
    for (i=0, mptr= clone->marker; mptr!=NULL && addit==TRUE; 
                                   i++, mptr = mptr->nextmarker)
    {
         if(strcmp(mptr->marker,name)==0) /* clone has marker */
         {
            addit = FALSE;
            for (i=0; i<cm; i++) /* so will not be removed */
               if (strcmp(name,clone_marks[i])==0) {
                   clone_marks[i][0] = '\0';
                   break;
               }
            if(!fppInsert(markerdata,name,&index2, markerOrder))
            { 
               mkptr = arrp(markerdata,index2,MARKER);
               if (mkptr->status == -1) mkptr->status = AUTO;
                     /* cari - this is not being used by us as least */
               if (mptr->weak != weak) {
                   mptr->weak = weak;
                   if (mkptr->cloneindex == index)
                        mkptr->weak = weak;
                   else 
                      for (markclptr = mkptr->nextclone;
                           markclptr->nextclone!=NULL;
	                   markclptr = markclptr->nextclone)
                             if (markclptr->cloneindex == index) {
                                  markclptr->weak = weak;
                                  break;
                              }
                }
            } else fprintf(stderr,"**** FPC error; cannot find marker %s\n",name);
         }
    }
    if (addit==FALSE) {
       if(!fppInsert(markerdata,name,&index2, markerOrder)){
          mkptr = arrp(markerdata,index2,MARKER);
          if (mkptr->type!= markertype) { /* ADD 02jan01 */
              /* CAS 8/31/01 - sanger center stuff */
              if (merge_flag && markertype==markPCR) {
                  printf("Marker %16s electronic\n",mkptr->marker);
                  sprintf(str1,"eConfirmed %s",mkptr->marker);
                  addremark(str1,index);
                  confirmed++;
              }
              else {
                  mkptr->type = markertype; 
                  marktypechg++;
              }
          }
        }
        continue;
    }
    chg=1;
    
    if(!fppInsert(markerdata,name,&index2, markerOrder)){
       mkptr = arrp(markerdata,index2,MARKER);
       mkptr->count++;  /* WN 04/04 was not getting incremented */
       mkptr->type= markertype; /* ADD 02jan01 */
       if (mkptr->status != NEW && mkptr->status != UPDATED){
           mkptr->status = UPDATED;
	   settime(&mkptr->modified_date);
	   updatemarkers++;
       }
       if (mkptr->cloneindex == -1) {
           mkptr->cloneindex = index;
           mkptr->weak = weak;
       }
       else {
          markclptr = mkptr->nextclone;
          if(markclptr!=NULL){
             while (markclptr->nextclone!=NULL)
	          markclptr = markclptr->nextclone;
	     markclptr->nextclone  = (struct markerclone *)
                      messalloc((sizeof(struct markerclone)));
	     markclptr= markclptr->nextclone;
          }
          else{
	    mkptr->nextclone  = (struct markerclone *)
                      messalloc((sizeof(struct markerclone)));
	    markclptr = mkptr->nextclone;
          }
          markclptr->cloneindex =  index;
          markclptr->weak =  weak;
          markclptr->nextclone = NULL;
        }
     }
     else { /* new marker */
        if (ace_debug) printf("new marker %s",name);
        newmarkers++;
        strcpy(marker.marker, name);
        marker.colour = 0;
	marker.status = NEW;
        marker.count = 1;  /* WN 04/04 was not getting initialized */
	marker.minicontigbox = marker.textbox = marker.textbox2 = 0;
	marker.type= markertype;
	settime(&marker.creation_date); 
        settime(&marker.modified_date);
	marker.anchor = FALSE;
        marker.anchor_pos = FLT_MIN;
        marker.anchor_bin[0] = '\0';
	marker.type= markertype;
	marker.pos = NULL;
	marker.nextclone = NULL;
        marker.cloneindex =  index;
        marker.weak =  weak;
        marker.remark=NULL;  
	array(markerdata,index2,MARKER) = marker;
     }
     clonemarks++;
     if(clone->marker == NULL){
        clone->marker  = (struct markertop *)
                   messalloc((sizeof(struct markertop)));	
        clone->marker->markerindex = index2;
        clone->marker->weak = weak;
        clone->marker->new = TRUE;
        strcpy(clone->marker->marker,name);
        clone->marker->nextmarker = NULL;
     }
     else{
        toppointer = clone->marker;
        while(toppointer->nextmarker !=NULL)
	     toppointer = toppointer->nextmarker;
        toppointer->nextmarker = (struct markertop *)
                   messalloc((sizeof(struct markertop)));
        toppointer = toppointer->nextmarker;
        toppointer->nextmarker = NULL;
        toppointer->markerindex = index2;
        toppointer->weak = weak;
        toppointer->new = TRUE;
        strcpy(toppointer->marker,name);
     }
  } /* end input */

  if (index != -1) { /* finish off last clone */
     if (removemarks(cm,  index)) {c_rm++; chg = 1;}
     if (chg) settime(&(clone->modified_date)); 
  }
  if (ace_debug) printmarkers("before remove markers");

  if (!merge_flag) {
    markerdata2 = arrayCreate(arrayMax(markerdata),MARKER);
    j = removed = 0;
    for(i=0;i<arrayMax(markerdata);i++){
      marker = arr(markerdata,i,MARKER);
      if(marker.status == -1){
        removed++;
        printf("Remove marker %s\n",marker.marker);
        for (c=0; c<arrayMax(acedata); c++) {
            clp = arrp(acedata, c, CLONE);
            for (mptr = clp->marker; mptr != NULL; mptr = mptr->nextmarker) {
               if(strcmp(mptr->marker,marker.marker)==0) {
                  strcpy(clone_marks[0], mptr->marker);
                  removemarks(1, c);
                  break; 
               }
            }
        }
      }
      else {
         array(markerdata2,j,MARKER) = marker;
         j++;
      }
    }
    arrayDestroy(markerdata);
    markerdata = markerdata2;

    for (i=0; i<arrayMax(acedata); i++) {
       clone = arrp(acedata, i, CLONE);
       if (!clone->selected) continue;
       clone->selected = 0;
       for (cm=0, mptr= clone->marker; mptr!=NULL; cm++, mptr = mptr->nextmarker)
       {
            strcpy(clone_marks[cm],mptr->marker);
            if (cm >= CLONE_MARKER_MAX) {
                printf("Exceeded marker limit %d for clone %s\n",CLONE_MARKER_MAX,
                           clone->clone);
                continue;
            }
        }
        if (cm==0) continue;
        printf("Removed all markers for %s\n",clone->clone);
        if (removemarks(cm,  i)) {c_rm++; chg = 1;}
     }
  }
                      /* markercorrect indices **/
  for(i=0;i<arrayMax(acedata);i++){ 
    clp = arrp(acedata,i,CLONE);
    for (mptr = clp->marker; mptr != NULL; mptr = mptr->nextmarker) {
      if(fppFind(markerdata,mptr->marker,&index, markerOrder))
	mptr->markerindex = index;
      else
	printf("FPC ERROR clone %s no marker %s\n",clp->clone, mptr->marker);
    }
  } 
  if (type==0) printf("Merge complete\n");
  else printf("Replace complete\n");
  if(updateclones >0) {
    if (merge_flag) 
       printf(
         " Modified Clones %d  Add clone markers %d  Electronic %d  eConfirmed %d\n",
                         updateclones, clonemarks, electronic, confirmed);
    else
       printf(
         " Modified Clones %d  Add clone markers %d  Delete clone markers %d\n",
                         updateclones, clonemarks, del_clone_marks);
  }
  else
    printf(" No clones updated.\n");

  if(newmarkers >0)
    printf(" New markers %d\n",newmarkers);
  else
    printf(" No new markers added\n");
  if (!merge_flag) {
    if(removed)
      printf(" Removed markers %d\n",removed);
    else 
      printf(" No markers removed\n");
  }
  if(updatemarkers >0)
    printf(" Existing markers updated %d\n",updatemarkers);
  else
    printf(" No existing markers updated.\n");

  if (marktypechg>0) 
    printf("Marker type change %d\n",marktypechg);

  for(i=0;i<arrayMax(acedata);i++)
    arrp(acedata,i,CLONE)->selected = 0;
  return(1);
}

/*******************************************************/
void Zmerge_batch(char *dir, char *file) 
{
char buf[MAXPATHLEN];
FILE *fpace;

  if (dir[0]=='\0' && dirName[0]!='\0') 
     sprintf(mergedir, "%s/updates", dirName);
  else if (dirName[0]=='\0') 
     sprintf(mergedir, "updates");
  else 
     sprintf(mergedir, "%s", dir);
  sprintf(buf,"%s/%s", mergedir, file);
  printf("Read %s/%s\n", mergedir, file);
  fpace = fopen(buf,"r");
  if(fpace!=0)  {
     if (readmarkerfile(fpace, 1)) {
          open_framework();
          sequencenew();
     }
     save_fpc_safe();
  }
  else printf("Error opening %s\n",buf);
}
static void printmarkers (char *msg)
{
  int j;
  struct markerctgpos *pos;
  struct markerclone *clones;
  struct marker *marker;

  printf(">>> %s\n",msg);
  for(j=0;j<arrayMax(markerdata);j++){
    marker = arrp(markerdata,j,MARKER);
    printf("Marker %14s (%d): ",marker->marker, marker->status);
    for (pos = marker->pos; pos!= NULL; pos= pos->next) 
          printf("%d ",pos->ctg);
    printf(": %s ",arrp(acedata,marker->cloneindex,CLONE)->clone);
    for (clones = marker->nextclone; clones!=NULL;clones = clones->nextclone)
       printf("%s ",arrp(acedata,clones->cloneindex,CLONE)->clone);
    printf("\n");
  }

}
